<!-- 起步 -->
<template>
	<div class='container'>
		<a-layout>
			<a-layout-content class='layout-content' ref='content'>
				<a-card>
					<h1>登录与支付</h1>
					<div id="box1" class="box">
						<h2>1. 创建 settle 分支</h2>
						<p>运行如下的命令，基于 master 分支在本地创建 settle 子分支，用来开发分类页面相关的功能：</p>
						<code-mirror :value="code[0]" :options="cmOptions"> </code-mirror>
					</div>
					<div class="box" id="box2">
						<h2>2. 点击结算按钮进行条件判断</h2>
						<div class="tip">
							说明：用户点击了结算按钮之后，需要先后判断是否勾选了要结算的商品、是否选择了收货地址、是否登录。
						</div>
						<ol>
							<li>
								<p>在 my-settle 组件中，为结算按钮绑定点击事件处理函数：</p>
								<code-mirror :value="code[1]" :options="cmOptions1"> </code-mirror>
							</li>
							<li>
								<p>在 my-settle 组件的 methods 节点中声明 settlement 事件处理函数如下：</p>
								<code-mirror :value="code[2]" :options="cmOptions"> </code-mirror>
							</li>
							<li>
								<p>在 my-settle 组件中，使用 mapGetters 辅助函数，从 m_user 模块中将 addstr 映射到当前组件中使用：</p>
								<code-mirror :value="code[3]" :options="cmOptions"> </code-mirror>
							</li>
							<li>
								<p>在 store/user.js 模块的 state 节点中，声明 token 字符串：</p>
								<code-mirror :value="code[4]" :options="cmOptions"> </code-mirror>
							</li>
							<li>
								<p>在 my-settle 组件中，使用 mapState 辅助函数，从 m_user 模块中将 token 映射到当前组件中使用：</p>
								<code-mirror :value="code[5]" :options="cmOptions"> </code-mirror>
							</li>
						</ol>
					</div>
					<div class="box" id="box3">
						<h2>3. 登录</h2>
						<div class="item" id="box3-1">
							<h3>3-1. 定义 my 页面的编译模式</h3>
							<ol>
								<li>
									<p>点击 微信开发者工具 工具栏上的编译模式下拉菜单，选择 添加编译模式：</p>
									<el-image style="width: 100%;" :src="srcList[0]" fit="contain"
										:preview-src-list="srcList">
									</el-image>
								</li>
								<li>
									<p>勾选启动页面的路径之后，点击确定按钮：</p>
									<el-image style="width: 100%;" :src="srcList[1]" fit="contain"
										:preview-src-list="srcList">
									</el-image>
								</li>	
							</ol>
						</div>
						<div class="item" id="box3-2">
							<h3>3-2. 实现登录和用户信息组件的按需展示</h3>
							<ol>
								<li>
									<p>在 components 目录中新建登录组件：</p>
									<el-image style="width: 100%;" :src="srcList[2]" fit="contain"
										:preview-src-list="srcList">
									</el-image>
								</li>
								<li>
									<p>在 components 目录中新建用户信息组件：</p>
									<el-image style="width: 100%;" :src="srcList[3]" fit="contain"
										:preview-src-list="srcList">
									</el-image>
								</li>	
								<li>
									<p>在 my.vue 页面中，通过 mapState 辅助函数，导入需要的 token 字符串：</p>
									<code-mirror :value="code[6]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 my.vue 页面中，实现登录组件和用户信息组件的按需展示：</p>
									<code-mirror :value="code[7]" :options="cmOptions1"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box3-3">
							<h3>3-3. 实现登录组件的基本布局</h3>
							<ol>
								<li>
									<p>为 my-login 组件定义如下的 UI 结构：</p>
									<code-mirror :value="code[8]" :options="cmOptions1"> </code-mirror>
								</li>
								<li>
									<p>美化登录组件的样式：</p>
									<code-mirror :value="code[9]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box3-4">
							<h3>3-4. 点击登录按钮获取微信用户的基本信息</h3>
							<div class="tip">
								需求描述：需要获取微信用户的头像、昵称等基本信息。
							</div>
							<ol>
								<li>
									<p>为登录的 button 按钮绑定 open-type="getUserInfo" 属性，表示点击按钮时，希望获取用户的基本信息：</p>
									<code-mirror :value="code[10]" :options="cmOptions1"> </code-mirror>
								</li>
								<li>
									<p>在 methods 节点中声明 getUserInfo 事件处理函数如下：</p>
									<code-mirror :value="code[11]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box3-5">
							<h3>3-5. 将用户的基本信息存储到 vuex</h3>
							<ol>
								<li>
									<p>在 store/user.js 模块的 state 节点中，声明 userinfo 的信息对象如下：</p>
									<code-mirror :value="code[12]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 store/user.js 模块的 mutations 节点中，声明如下的两个方法：</p>
									<code-mirror :value="code[13]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>使用 mapMutations 辅助函数，将需要的方法映射到 my-login 组件中使用：</p>
									<code-mirror :value="code[14]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box3-6">
							<h3>3-6. 登录获取 Token 字符串</h3>
							<div class="tip">
								需求说明：当获取到了微信用户的基本信息之后，还需要进一步调用登录相关的接口，从而换取登录成功之后的 Token 字符串。
							</div>
							<ol>
								<li>
									<p>在 getUserInfo 方法中，预调用 this.getToken() 方法，同时把获取到的用户信息传递进去：</p>
									<code-mirror :value="code[15]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 methods 中定义 getToken 方法，调用登录相关的 API，实现登录的功能：</p>
									<code-mirror :value="code[16]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box3-7">
							<h3>3-7. 将 Token 存储到 vuex</h3>
							<ol>
								<li>
									<p>在 store/user.js 模块的 mutations 节点中，声明如下的两个方法：</p>
									<code-mirror :value="code[17]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>修改 store/user.js 模块的 state 节点如下：</p>
									<code-mirror :value="code[18]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 my-login 组件中，把 vuex 中的 updateToken 方法映射到当前组件中使用：</p>
									<code-mirror :value="code[19]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
					</div>
					<div class="box" id="box4">
						<h2>4. 用户信息</h2>
						<div class="item" id="box4-1">
							<h3>4-1. 实现用户头像昵称区域的基本布局</h3>
							<ol>
								<li>
									<p>在 my-userinfo 组件中，定义如下的 UI 结构：</p>
									<code-mirror :value="code[20]" :options="cmOptions1"> </code-mirror>
								</li>
								<li>
									<p>美化当前组件的样式：</p>
									<code-mirror :value="code[21]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 my.vue 页面中，为最外层包裹性质的 view 容器，添加 class="my-container" 的类名，并美化样式如下：</p>
									<code-mirror :value="code[22]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box4-2">
							<h3>4-2. 渲染用户的头像和昵称</h3>
							<ol>
								<li>
									<p>在 my-userinfo 组件中，通过 mapState 辅助函数，将需要的成员映射到当前组件中使用：</p>
									<code-mirror :value="code[23]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>将用户的头像和昵称渲染到页面中：</p>
									<code-mirror :value="code[24]" :options="cmOptions1"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box4-3">
							<h3>4-3. 渲染第一个面板区域</h3>
							<ol>
								<li>
									<p>在 my-userinfo 组件中，定义如下的 UI 结构：</p>
									<code-mirror :value="code[25]" :options="cmOptions1"> </code-mirror>
								</li>
								<li>
									<p>美化第一个面板的样式：</p>
									<code-mirror :value="code[26]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box4-4">
							<h3>4-4. 渲染第二个面板区域</h3>
							<ol>
								<li>
									<p>定义第二个面板区域的 UI 结构：</p>
									<code-mirror :value="code[27]" :options="cmOptions1"> </code-mirror>
								</li>
								<li>
									<p>对之前的 SCSS 样式进行改造，从而美化第二个面板的样式：</p>
									<code-mirror :value="code[28]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box4-5">
							<h3>4-5. 渲染第三个面板区域</h3>
							<ol>
								<li>
									<p>定义第三个面板区域的 UI 结构：</p>
									<code-mirror :value="code[29]" :options="cmOptions1"> </code-mirror>
								</li>
								<li>
									<p>美化第三个面板区域的样式：</p>
									<code-mirror :value="code[30]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box4-6">
							<h3>4-6. 实现退出登录的功能</h3>
							<ol>
								<li>
									<p>为第三个面板区域中的 退出登录 项绑定 click 点击事件处理函数：</p>
									<code-mirror :value="code[31]" :options="cmOptions1"> </code-mirror>
								</li>
								<li>
									<p>在 my-userinfo 组件的 methods 节点中定义 logout 事件处理函数：</p>
									<code-mirror :value="code[32]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>使用 mapMutations 辅助方法，将需要用到的 mutations 方法映射到当前组件中：</p>
									<code-mirror :value="code[33]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
					</div>
					<div class="box" id="box5">
						<h2>5. 三秒后自动跳转</h2>
						<div class="item" id="box5-1">
							<h3>5-1. 三秒后自动跳转到登录页面</h3>
							<div class="tip">
								需求描述：在购物车页面，当用户点击 “结算” 按钮时，如果用户没有登录，则 3 秒后自动跳转到登录页面
							</div>
							<ol>
								<li>
									<p>在 my-settle 组件的 methods 节点中，声明一个叫做 showTips 的方法，专门用来展示倒计时的提示消息：</p>
									<code-mirror :value="code[34]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 data 节点中声明倒计时的秒数：</p>
									<code-mirror :value="code[35]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>改造 结算 按钮的 click 事件处理函数，如果用户没有登录，则预调用一个叫做 delayNavigate 的方法，进行倒计时的导航跳转：</p>
									<code-mirror :value="code[36]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>定义 delayNavigate 方法，初步实现倒计时的提示功能：</p>
									<code-mirror :value="code[37]" :options="cmOptions"> </code-mirror>
									<div class="tip">上述代码的问题：定时器不会自动停止，此时秒数会出现等于 0 或小于 0 的情况！</div>
								</li>
								<li>
									<p>在 data 节点中声明定时器的 Id 如下：</p>
									<code-mirror :value="code[38]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>改造 delayNavigate 方法如下：</p>
									<code-mirror :value="code[39]" :options="cmOptions"> </code-mirror>
									<div class="tip">
										上述代码的问题：seconds 秒数不会被重置，导致第 2 次，3 次，n 次 的倒计时跳转功能无法正常工作	
									</div>
								</li>
								<li>
									<p>进一步改造 delayNavigate 方法，在执行此方法时，立即将 seconds 秒数重置为 3 即可：</p>
									<code-mirror :value="code[40]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box5-2">
							<h3>5-2. 登录成功之后再返回之前的页面</h3>
							<div class="tip">核心实现思路：在自动跳转到登录页面成功之后，把返回页面的信息存储到 vuex 中，从而方便登录成功之后，根据返回页面的信息重新跳转回去。</div>
							<div class="tip">返回页面的信息对象，主要包含 { openType, from } 两个属性，其中 openType 表示以哪种方式导航回之前的页面；from 表示之前页面的 url 地址；</div>
							<ol>
								<li>
									<p>在 store/user.js 模块的 state 节点中，声明一个叫做 redirectInfo 的对象如下：</p>
									<code-mirror :value="code[41]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 store/user.js 模块的 mutations 节点中，声明一个叫做 updateRedirectInfo 的方法：</p>
									<code-mirror :value="code[42]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 my-settle 组件中，通过 mapMutations 辅助方法，把 m_user 模块中的 updateRedirectInfo 方法映射到当前页面中使用：</p>
									<code-mirror :value="code[43]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>改造 my-settle 组件 methods 节点中的 delayNavigate 方法，当成功跳转到 my 页面 之后，将重定向的信息对象存储到 vuex 中：</p>
									<code-mirror :value="code[44]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 my-login 组件中，通过 mapState 和 mapMutations 辅助方法，将 vuex 中需要的数据和方法，映射到当前页面中使用：</p>
									<code-mirror :value="code[45]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>改造 my-login 组件中的 getToken 方法，当登录成功之后，预调用 this.navigateBack() 方法返回登录之前的页面：	</p>
									<code-mirror :value="code[46]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 my-login 组件中，声明 navigateBack 方法如下：</p>
									<code-mirror :value="code[47]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
					</div>
					<div class="box" id="box6">
						<h2>6. 微信支付</h2>
						<div class="item" id="box6-1">
							<h3>6-1. 在请求头中添加 Token 身份认证的字段</h3>
							<ol>
								<li>
									<p>原因说明：只有在登录之后才允许调用支付相关的接口，所以必须为有权限的接口添加身份认证的请求头字段</p>
								</li>
								<li>
									<p>打开项目根目录下的 main.js，改造 $http.beforeRequest 请求拦截器中的代码如下：</p>
									<code-mirror :value="code[48]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box6-2">
							<h3>6-2. 微信支付的流程</h3>
							<ol>
								<li>
									<h4>创建订单</h4>
									<ul>
										<li>请求创建订单的 API 接口：把（订单金额、收货地址、订单中包含的商品信息）发送到服务器</li>
										<li>服务器响应的结果：订单编号</li>
									</ul>
								</li>
								<li>
									<h4>订单预支付</h4>
									<ul>
										<li>请求订单预支付的 API 接口：把（订单编号）发送到服务器</li>
										<li>服务器响应的结果：订单预支付的参数对象，里面包含了订单支付相关的必要参数</li>
									</ul>
								</li>
								<li>
									<h4>发起微信支付</h4>
									<ul>
										<li>调用 uni.requestPayment() 这个 API，发起微信支付；把步骤 2 得到的 “订单预支付对象” 作为参数传递给 uni.requestPayment() 方法</li>
										<li>监听 uni.requestPayment() 这个 API 的 success，fail，complete 回调函数</li>
									</ul>
								</li>
							</ol>
						</div>
						<div class="item" id="box6-3">
							<h3>6-3. 创建订单</h3>
							<ol>
								<li>
									<p>改造 my-settle 组件中的 settlement 方法，当前三个判断条件通过之后，调用实现微信支付的方法：</p>
									<code-mirror :value="code[49]" :options="cmOptions"> </code-mirror>
								</li>
								<li>
									<p>在 my-settle 组件中定义 payOrder 方法如下，先实现创建订单的功能：</p>
									<code-mirror :value="code[50]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box6-4">
							<h3>6-4. 订单预支付</h3>
							<ol>
								<li>
									<p>改造 my-settle 组件的 payOrder 方法，实现订单预支付功能：</p>
									<code-mirror :value="code[51]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
						<div class="item" id="box6-5">
							<h3>6-5. 发起微信支付</h3>
							<ol>
								<li>
									<p>改造 my-settle 组件的 payOrder 方法，实现微信支付的功能：</p>
									<code-mirror :value="code[52]" :options="cmOptions"> </code-mirror>
								</li>
							</ol>
						</div>
					</div>
					<div id="box7" class="box">
						<h2>7. 分支的合并与提交</h2>
						<ol>
							<li>
								<p>将 settle 分支进行本地提交：</p>
								<code-mirror :value="code[53]" :options="cmOptions"> </code-mirror>
							</li>
							<li>
								<p>将本地的 settle 分支推送到码云：</p>
								<code-mirror :value="code[54]" :options="cmOptions"> </code-mirror>
							</li>
							<li>
								<p>将本地 settle 分支中的代码合并到 master 分支：</p>
								<code-mirror :value="code[55]" :options="cmOptions"> </code-mirror>
							</li>
							<li>
								<p>删除本地的 settle 分支：</p>
								<code-mirror :value="code[56]" :options="cmOptions"> </code-mirror>
							</li>
						</ol>
					</div>
				</a-card>
			</a-layout-content>
			<a-layout-sider class='layout-sider' width='300'>
				<a-anchor affix :getContainer='getContainer' :wrapperStyle="{maxHeight: 'calc( 100vh - 120px)'}"	@click="handleClick">
					<a-anchor-link href="#box1" title="1. 创建 settle 分支"></a-anchor-link>
					<a-anchor-link href="#box2" title="2. 点击结算按钮进行条件判断"></a-anchor-link>
					<a-anchor-link href="#box3" title="3. 登录">
						<a-anchor-link href="#box3-1" title="3-1. 定义 my 页面的编译模式"></a-anchor-link>
						<a-anchor-link href="#box3-2" title="3-2. 实现登录和用户信息组件的按需展示"></a-anchor-link>
						<a-anchor-link href="#box3-3" title="3-3. 实现登录组件的基本布局"></a-anchor-link>
						<a-anchor-link href="#box3-4" title="3-4. 点击登录按钮获取微信用户的基本信息"></a-anchor-link>
						<a-anchor-link href="#box3-5" title="3-5. 将用户的基本信息存储到 vuex"></a-anchor-link>
						<a-anchor-link href="#box3-6" title="3-6. 登录获取 Token 字符串"></a-anchor-link>
						<a-anchor-link href="#box3-7" title="3-7. 将 Token 存储到 vuex"></a-anchor-link>
					</a-anchor-link>
					<a-anchor-link href="#box4" title="4. 用户信息">
						<a-anchor-link href="#box4-1" title="4-1. 实现用户头像昵称区域的基本布局"></a-anchor-link>
						<a-anchor-link href="#box4-2" title="4-2. 渲染用户的头像和昵称"></a-anchor-link>
						<a-anchor-link href="#box4-3" title="4-3. 渲染第一个面板区域"></a-anchor-link>
						<a-anchor-link href="#box4-4" title="4-4. 渲染第二个面板区域"></a-anchor-link>
						<a-anchor-link href="#box4-5" title="4-5. 渲染第三个面板区域"></a-anchor-link>
						<a-anchor-link href="#box4-6" title="4-6. 实现退出登录的功能"></a-anchor-link>
					</a-anchor-link>
					<a-anchor-link href="#box5" title="5. 三秒后自动跳转">
						<a-anchor-link href="#box5-1" title="5-1. 三秒后自动跳转到登录页面"></a-anchor-link>
						<a-anchor-link href="#box5-2" title="5-2. 登录成功之后再返回之前的页面"></a-anchor-link>
					</a-anchor-link>
					<a-anchor-link href="#box6" title="6. 微信支付">
						<a-anchor-link href="#box6-1" title="6-1. 在请求头中添加 Token 身份认证的字段"></a-anchor-link>
						<a-anchor-link href="#box6-2" title="6-2. 微信支付的流程"></a-anchor-link>
						<a-anchor-link href="#box6-3" title="6-3. 创建订单"></a-anchor-link>
						<a-anchor-link href="#box6-4" title="6-4. 订单预支付"></a-anchor-link>
						<a-anchor-link href="#box6-5" title="6-5. 发起微信支付"></a-anchor-link>
					</a-anchor-link>
					<a-anchor-link href="#box7" title="7. 分支的合并与提交"></a-anchor-link>
				</a-anchor>
			</a-layout-sider>
		</a-layout>
	</div>
</template>
<script>
	import {
		loginPay
	} from '../../util/code.js'
	import img1 from '@/assets/loginPay1.png'
	import img2 from '@/assets/loginPay2.png'
	import img3 from '@/assets/loginPay3.png'
	import img4 from '@/assets/loginPay4.png'
	export default {
		name: 'loginPay',
		data() {
			return {
				srcList:[img1,img2,img3,img4],
				cmOptions: {
					mode: "javascript",
					theme: "base16-dark",
					disabled: true
				},
				cmOptions1: {
					mode: "vue",
					theme: "base16-dark",
					disabled: true
				},
				code: loginPay
			}
		},
		methods: {
			getContainer() {
				return this.$refs.content.$el
			},
			handleClick(e, link) {
				// 阻止点击的默认事件修改路由
				e.preventDefault();
				if (link.href) {
					let ele = document.getElementById(link.href);
					ele && ele.scrollIntoView({
						block: 'start',
						behavior: 'smooth'
					});
				}
			}
		}
	}
</script>
<style scoped>
</style>
